home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / dev / c / mkid.lha / src / scan-c.c < prev    next >
C/C++ Source or Header  |  1991-02-01  |  7KB  |  294 lines

  1. /* Copyright (c) 1986, Greg McGary */
  2. static char sccsid[] = "@(#)scan-c.c    1.1 86/10/09";
  3.  
  4. #include    "bool.h"
  5. #include    <stdio.h>
  6. #include    "string.h"
  7. #include    "id.h"
  8.  
  9. char *getCId();
  10. void setCArgs();
  11.  
  12. static void clrCtype();
  13. static void setCtype();
  14.  
  15. #define    I1    0x0001    /* 1st char of an identifier [a-zA-Z_] */
  16. #define    DG    0x0002    /* decimal digit [0-9] */
  17. #define    NM    0x0004    /* extra chars in a hex or long number [a-fA-FxXlL] */
  18. #define    C1    0x0008    /* C comment introduction char: / */
  19. #define    C2    0x0010    /* C comment termination  char: * */
  20. #define    Q1    0x0020    /* single quote: ' */
  21. #define    Q2    0x0040    /* double quote: " */
  22. #define    ES    0x0080    /* escape char: \ */
  23. #define    NL    0x0100    /* newline: \n */
  24. #define    EF    0x0200    /* EOF */
  25. #define    SK    0x0400    /* Make these chars valid for names within strings */
  26.  
  27. /*
  28.     character class membership macros:
  29. */
  30. #define    ISDIGIT(c)    ((rct)[c]&(DG))        /* digit */
  31. #define    ISNUMBER(c)    ((rct)[c]&(DG|NM))    /* legal in a number */
  32. #define    ISEOF(c)    ((rct)[c]&(EF))        /* EOF */
  33. #define    ISID1ST(c)    ((rct)[c]&(I1))        /* 1st char of an identifier */
  34. #define    ISIDREST(c)    ((rct)[c]&(I1|DG))    /* rest of an identifier */
  35. #define    ISSTRKEEP(c)    ((rct)[c]&(I1|DG|SK))    /* keep contents of string */
  36. /*
  37.     The `BORING' classes should be skipped over
  38.     until something interesting comes along...
  39. */
  40. #define    ISBORING(c)    (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1)))    /* fluff */
  41. #define    ISCBORING(c)    (!((rct)[c]&(EF|C2)))    /* comment fluff */
  42. #define    ISQ1BORING(c)    (!((rct)[c]&(EF|NL|Q1|ES)))    /* char const fluff */
  43. #define    ISQ2BORING(c)    (!((rct)[c]&(EF|NL|Q2|ES)))    /* quoted str fluff */
  44.  
  45. static short idctype[] = {
  46.  
  47.     EF,
  48.  
  49.     /*      0       1       2       3       4       5       6       7   */
  50.     /*    -----   -----   -----   -----   -----   -----   -----   ----- */
  51.  
  52.     /*000*/    0,    0,    0,    0,    0,    0,    0,    0,
  53.     /*010*/    0,    0,    NL,    0,    0,    0,    0,    0,
  54.     /*020*/    0,    0,    0,    0,    0,    0,    0,    0,
  55.     /*030*/    0,    0,    0,    0,    0,    0,    0,    0,
  56.     /*040*/    0,    0,    Q2,    0,    0,    0,    0,    Q1,
  57.     /*050*/    0,    0,    C2,    0,    0,    0,    0,    C1,
  58.     /*060*/    DG,    DG,    DG,    DG,    DG,    DG,    DG,    DG,    
  59.     /*070*/    DG,    DG,    0,    0,    0,    0,    0,    0,
  60.     /*100*/    0,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1,
  61.     /*110*/    I1,    I1,    I1,    I1,    I1|NM,    I1,    I1,    I1,
  62.     /*120*/    I1,    I1,    I1,    I1,    I1,    I1,    I1,    I1,
  63.     /*130*/    I1|NM,    I1,    I1,    0,    ES,    0,    0,    I1,
  64.     /*140*/    0,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1,
  65.     /*150*/    I1,    I1,    I1,    I1,    I1|NM,    I1,    I1,    I1,
  66.     /*160*/    I1,    I1,    I1,    I1,    I1,    I1,    I1,    I1,
  67.     /*170*/    I1|NM,    I1,    I1,    0,    0,    0,    0,    0,
  68.  
  69.     /*200*/    0,    0,    0,    0,    0,    0,    0,    0,
  70.     /*210*/    0,    0,    0,    0,    0,    0,    0,    0,
  71.     /*220*/    0,    0,    0,    0,    0,    0,    0,    0,
  72.     /*230*/    0,    0,    0,    0,    0,    0,    0,    0,
  73.     /*240*/    0,    0,    0,    0,    0,    0,    0,    0,
  74.     /*250*/    0,    0,    0,    0,    0,    0,    0,    0,
  75.     /*260*/    0,    0,    0,    0,    0,    0,    0,    0,
  76.     /*270*/    0,    0,    0,    0,    0,    0,    0,    0,
  77.     /*300*/    0,    0,    0,    0,    0,    0,    0,    0,
  78.     /*310*/    0,    0,    0,    0,    0,    0,    0,    0,
  79.     /*320*/    0,    0,    0,    0,    0,    0,    0,    0,
  80.     /*330*/    0,    0,    0,    0,    0,    0,    0,    0,
  81.     /*340*/    0,    0,    0,    0,    0,    0,    0,    0,
  82.     /*350*/    0,    0,    0,    0,    0,    0,    0,    0,
  83.     /*360*/    0,    0,    0,    0,    0,    0,    0,    0,
  84.     /*370*/    0,    0,    0,    0,    0,    0,    0,    0,
  85.  
  86. };
  87.  
  88. static bool eatUnder = TRUE;
  89.  
  90. /*
  91.     Grab the next identifier the C source
  92.     file opened with the handle `inFILE'.
  93.     This state machine is built for speed, not elegance.
  94. */
  95. char *
  96. getCId(inFILE, flagP)
  97.     FILE        *inFILE;
  98.     int        *flagP;
  99. {
  100.     static char    idBuf[BUFSIZ];
  101.     static bool    newLine = TRUE;
  102.     register short    *rct = &idctype[1];
  103.     register int    c;
  104.     register char    *id = idBuf;
  105.  
  106. top:
  107.     c = getc(inFILE);
  108.     if (newLine) {
  109.         newLine = FALSE;
  110.         if (c != '#')
  111.             goto next;
  112.         while (ISBORING(c))
  113.             c = getc(inFILE);
  114.         if (!ISID1ST(c))
  115.             goto next;
  116.         id = idBuf;
  117.         *id++ = c;
  118.         while (ISIDREST(c = getc(inFILE)))
  119.             *id++ = c;
  120.         *id = '\0';
  121.         if (strcmp(idBuf, "include") == 0) {
  122.             while (c != '"' && c != '<')
  123.                 c = getc(inFILE);
  124.             id = idBuf;
  125.             *id++ = c = getc(inFILE);
  126.             while ((c = getc(inFILE)) != '"' && c != '>')
  127.                 *id++ = c;
  128.             *id = '\0';
  129.             *flagP = IDN_STRING;
  130.             return idBuf;
  131.         }
  132.         if (strncmp(idBuf, "if", 2) == 0
  133.         || strcmp(idBuf, "define")  == 0
  134.         || strcmp(idBuf, "undef")   == 0)
  135.             goto next;
  136.         while (c != '\n')
  137.             c = getc(inFILE);
  138.         newLine = TRUE;
  139.         goto top;
  140.     }
  141.  
  142. next:
  143.     while (ISBORING(c))
  144.         c = getc(inFILE);
  145.  
  146.     switch (c)
  147.     {
  148.     case '"':
  149.         id = idBuf;
  150.         *id++ = c = getc(inFILE);
  151.         for (;;) {
  152.             while (ISQ2BORING(c))
  153.                 *id++ = c = getc(inFILE);
  154.             if (c == '\\') {
  155.                 *id++ = c = getc(inFILE);
  156.                 continue;
  157.             } else if (c != '"')
  158.                 goto next;
  159.             break;
  160.         }
  161.         *--id = '\0';
  162.         id = idBuf;
  163.         while (ISSTRKEEP(*id))
  164.             id++;
  165.         if (*id || id == idBuf) {
  166.             c = getc(inFILE);
  167.             goto next;
  168.         }
  169.         *flagP = IDN_STRING;
  170.         if (eatUnder && idBuf[0] == '_' && idBuf[1])
  171.             return &idBuf[1];
  172.         else
  173.             return idBuf;
  174.         
  175.     case '\'':
  176.         c = getc(inFILE);
  177.         for (;;) {
  178.             while (ISQ1BORING(c))
  179.                 c = getc(inFILE);
  180.             if (c == '\\') {
  181.                 c = getc(inFILE);
  182.                 continue;
  183.             } else if (c == '\'')
  184.                 c = getc(inFILE);
  185.             goto next;
  186.         }
  187.  
  188.     case '/':
  189.         if ((c = getc(inFILE)) != '*')
  190.             goto next;
  191.         c = getc(inFILE);
  192.         for (;;) {
  193.             while (ISCBORING(c))
  194.                 c = getc(inFILE);
  195.             if ((c = getc(inFILE)) == '/') {
  196.                 c = getc(inFILE);
  197.                 goto next;
  198.             } else if (ISEOF(c)) {
  199.                 newLine = TRUE;
  200.                 return NULL;
  201.             }
  202.         }
  203.  
  204.     case '\n':
  205.         newLine = TRUE;
  206.         goto top;
  207.  
  208.     default:
  209.         if (ISEOF(c)) {
  210.             newLine = TRUE;
  211.             return NULL;
  212.         }
  213.     name:
  214.         id = idBuf;
  215.         *id++ = c;
  216.         if (ISID1ST(c)) {
  217.             *flagP = IDN_NAME;
  218.             while (ISIDREST(c = getc(inFILE)))
  219.                 *id++ = c;
  220.         } else if (ISDIGIT(c)) {
  221.             *flagP = IDN_NUMBER;
  222.             while (ISNUMBER(c = getc(inFILE)))
  223.                 *id++ = c;
  224.         } else
  225.             fprintf(stderr, "junk: `\\%3o'", c);
  226.         ungetc(c, inFILE);
  227.         *id = '\0';
  228.         *flagP |= IDN_LITERAL;
  229.         return idBuf;
  230.     }
  231. }
  232.  
  233. static void
  234. setCtype(chars, type)
  235.     char        *chars;
  236.     int        type;
  237. {
  238.     short        *rct = &idctype[1];
  239.  
  240.     while (*chars)
  241.         rct[*chars++] |= type;
  242. }
  243. static void
  244. clrCtype(chars, type)
  245.     char        *chars;
  246.     int        type;
  247. {
  248.     short        *rct = &idctype[1];
  249.  
  250.     while (*chars)
  251.         rct[*chars++] &= ~type;
  252. }
  253.  
  254. extern char    *MyName;
  255. static void
  256. usage(lang)
  257.     char        *lang;
  258. {
  259.     fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang);
  260.     exit(1);
  261. }
  262. static char *cDocument[] =
  263. {
  264. "The C scanner arguments take the form -Sc<arg>, where <arg>",
  265. "is one of the following: (<cc> denotes one or more characters)",
  266. "  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.",
  267. "  -s<cc> . . . . Allow <cc> in string ids.",
  268. NULL
  269. };
  270. void
  271. setCArgs(lang, op, arg)
  272.     char        *lang;
  273.     int        op;
  274.     char        *arg;
  275. {
  276.     if (op == '?') {
  277.         document(cDocument);
  278.         return;
  279.     }
  280.     switch (*arg++)
  281.     {
  282.     case 'u':
  283.         eatUnder = (op == '+');
  284.         break;
  285.     case 's':
  286.         setCtype(arg, SK);
  287.         break;
  288.     default:
  289.         if (lang)
  290.             usage(lang);
  291.         break;
  292.     }
  293. }
  294.